﻿using Engine.FileFormats3D.WR2TerrainLoader.QadFile;
using Engine.WindowsFormsControls;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Scenario_Editor.CustomControls
{
    public partial class GroundControl : UserControl
    {
        #region Public Fields

        public const string DEFAULT_GROUND_NAME = "default";

        #endregion Public Fields

        #region Private Fields

        private const byte VERSION = 0x01;
        private bool duringControlUpdate = false;
        private List<Ground> grounds;

        #endregion Private Fields

        #region Public Constructors

        public GroundControl()
        {
            InitializeComponent();
            grounds = new List<Ground>();
            grounds.Add(GetCurrentGroundValues(DEFAULT_GROUND_NAME));
            this.listBox_Grounds.Items.Add(grounds[0]);
        }

        #endregion Public Constructors

        #region Public Delegates

        public delegate void OnGroundListChange(object sender, EventArgs e);

        #endregion Public Delegates

        #region Public Events

        public event OnGroundListChange groundListChange;

        #endregion Public Events

        #region Public Methods

        public List<Ground> GetGrounds()
        {
            return this.grounds;
        }

        #endregion Public Methods

        #region Internal Methods

        internal void FromStream(System.IO.BinaryReader br)
        {
            switch (br.ReadByte())
            {
                case 0x01:
                    LoadV1(br);
                    break;

                default:
                    throw new Exception("Unsupported Fileformat!!");
            }
        }

        // Internal Methods (3) 
        internal void LoadDefaultGrounds(string filename)
        {
            //throw new NotImplementedException();
        }

        internal void ToStream(System.IO.BinaryWriter bw)
        {
            bw.Write(VERSION);
            bw.Write(this.grounds.Count);
            for (int i = 0; i < this.grounds.Count; i++)
            {
                this.grounds[i].ToStream(bw);
            }
        }

        #endregion Internal Methods

        #region Private Methods

        private void button_DeleteGround_Click(object sender, EventArgs e)
        {
            ListBox.SelectedIndexCollection selectecdItems;
            do
            {
                selectecdItems = this.listBox_Grounds.SelectedIndices;
                if (selectecdItems.Count > 0)
                {
                    if (this.grounds[selectecdItems[0]].Name != DEFAULT_GROUND_NAME)
                    {
                        this.grounds.RemoveAt(selectecdItems[0]);
                        this.listBox_Grounds.Items.RemoveAt(selectecdItems[0]);
                    }
                    else
                    {
                        selectecdItems.Remove(selectecdItems[0]);
                    }

                    if (groundListChange != null)
                        groundListChange(this.grounds, EventArgs.Empty);
                }
            } while (selectecdItems.Count > 0);
        }

        private void button_RenameMaterial_Click(object sender, EventArgs e)
        {
            ListBox.SelectedIndexCollection selectecdItems = this.listBox_Grounds.SelectedIndices;
            using (NewGroundWindow newGroundWindow = new NewGroundWindow())
            {
                if (selectecdItems.Count > 0)
                {
                    newGroundWindow.SetGroundName(this.grounds[selectecdItems[0]].ToString());
                    if (DialogResult.OK == newGroundWindow.ShowDialog())
                    {
                        do
                        {
                            if (selectecdItems.Count > 0)
                            {
                                int index = selectecdItems[0];
                                Ground ground = this.grounds[index];
                                ground.Name = newGroundWindow.GetGroundName();
                                this.grounds[index] = ground;
                                this.listBox_Grounds.Items[index] = ground;
                                this.listBox_Grounds.SelectedIndices.Remove(index);
                            }
                        } while (selectecdItems.Count > 0);

                        if (groundListChange != null)
                            groundListChange(this.grounds, EventArgs.Empty);
                    }
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (NewGroundWindow newGroundWindow = new NewGroundWindow())
            {
                if (DialogResult.OK == newGroundWindow.ShowDialog())
                {
                    Ground ground = GetCurrentGroundValues(newGroundWindow.GetGroundName());

                    this.grounds.Add(ground);
                    this.listBox_Grounds.Items.Add(ground);

                    if (groundListChange != null)
                        groundListChange(this.grounds, EventArgs.Empty);
                }
            }
        }

        private Ground GetCurrentGroundValues(string groundName)
        {
            EnumSkidmarks skidmarks = GetSelectedSkidmark();
            EnumNoise noise = GetSelectedNoise();

            return new Ground(groundName,
                           (short)this.numericUpDown_FrontGrip.Value,
                           (short)this.numericUpDownRearGrip.Value,
                           (short)this.numericUpDown_Stickiness.Value,
                           (short)this.numericUpDown_Dirtiness.Value,
                           skidmarks,
                           noise, this.checkBox_NoCollision.Checked);
        }

        private EnumNoise GetSelectedNoise()
        {
            EnumNoise noise;
            if (this.radioButton_NoiseAsphalt.Checked)
                noise = EnumNoise.Asphalt;
            else if (this.radioButton_NoiseGrass.Checked)
                noise = EnumNoise.Gras;
            else if (this.radioButton_NoiseSand.Checked)
                noise = EnumNoise.Sand;
            else
                noise = EnumNoise.Unknown;
            return noise;
        }

        private EnumSkidmarks GetSelectedSkidmark()
        {
            EnumSkidmarks skidmarks;
            if (this.radioButton_SkidmarkAlwaysHard.Checked)
                skidmarks = EnumSkidmarks.AlwaysHard;
            else if (this.radioButton_SkidmarkAlwaysSoft.Checked)
                skidmarks = EnumSkidmarks.AlwaysSoft;
            else if (this.radioButton_SkidmarkHard.Checked)
                skidmarks = EnumSkidmarks.Hard;
            else
                skidmarks = EnumSkidmarks.None;
            return skidmarks;
        }

        private void listBox_Grounds_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listBox_Grounds.SelectedIndices.Count > 0)
            {
                Ground ground = this.grounds[this.listBox_Grounds.SelectedIndices[0]];
                SetControls(ground);
            }
        }

        private void LoadV1(System.IO.BinaryReader br)
        {
            this.grounds.Clear();
            this.listBox_Grounds.Items.Clear();

            int numberOfGrounds = br.ReadInt32();

            for (int i = 0; i < numberOfGrounds; i++)
            {
                this.grounds.Add(Ground.FromStream(br));
            }

            for (int i = 0; i < this.grounds.Count; i++)
            {
                this.listBox_Grounds.Items.Add(this.grounds[i]);
            }

            if (groundListChange != null)
                groundListChange(this.grounds, EventArgs.Empty);
        }

        private void SelectTextOnEnter(object sender, EventArgs e)
        {
            if (sender.GetType() == typeof(NumericUpDown))
            {
                NumericUpDown numericUpDown = sender as NumericUpDown;
                numericUpDown.Select(0, numericUpDown.ToString().Length);
            }
        }

        private void SetControls(Ground ground)
        {
            this.duringControlUpdate = true;
            // properties
            this.numericUpDown_Dirtiness.Value = ground.Dirtiness;
            this.numericUpDown_FrontGrip.Value = ground.FrontGrip;
            this.numericUpDown_Stickiness.Value = ground.Stickiness;
            this.numericUpDownRearGrip.Value = ground.RearGrip;

            // Noise
            switch (ground.Noise)
            {
                case EnumNoise.Asphalt:
                    this.radioButton_NoiseAsphalt.Checked = true;
                    break;

                case EnumNoise.Gras:
                    this.radioButton_NoiseGrass.Checked = true;
                    break;

                case EnumNoise.Sand:
                    this.radioButton_NoiseSand.Checked = true;
                    break;

                default:
                    this.radioButton_NoiseUnknown.Checked = true;
                    break;
            }

            // Skidmarks
            switch (ground.Skidmarks)
            {
                case EnumSkidmarks.AlwaysHard:
                    this.radioButton_SkidmarkAlwaysHard.Checked = true;
                    break;

                case EnumSkidmarks.AlwaysSoft:
                    this.radioButton_SkidmarkAlwaysSoft.Checked = true;
                    break;

                case EnumSkidmarks.Hard:
                    this.radioButton_SkidmarkHard.Checked = true;
                    break;

                default:
                    this.radioButton_SkidmarkNone.Checked = true;
                    break;
            }

            // Unknown

            // no Collision
            this.checkBox_NoCollision.Checked = ground.NoCollision;

            this.duringControlUpdate = false;
        }

        private void UpdateSelectedGrounds(object sender, EventArgs e)
        {
            if (!duringControlUpdate)
            {
                ListBox.SelectedIndexCollection selectecdItems = this.listBox_Grounds.SelectedIndices;

                for (int i = 0; i < selectecdItems.Count; i++)
                {
                    int index = selectecdItems[i];

                    Ground ground = GetCurrentGroundValues(this.grounds[index].Name);
                    this.grounds[index] = ground;
                    this.listBox_Grounds.Items[index] = ground;
                }
            }
        }

        #endregion Private Methods
    }
}